﻿namespace HZY.Framework.DependencyInjection.Services;

/// <summary>
/// 重写 ServiceProvider
/// 支持属性注入
/// </summary>
public class AutowiredServiceProvider : IServiceProvider, ISupportRequiredService
//, IServiceProviderIsService, IServiceProviderIsKeyedService //, IDisposable, IAsyncDisposable
{
    private readonly IServiceProvider _serviceProvider;

    public AutowiredServiceProvider(IServiceProvider serviceProvider)
    {
        _serviceProvider = serviceProvider;
    }

    public object GetRequiredService(Type serviceType)
    {
        var instance = _serviceProvider.GetRequiredService(serviceType);
        //Autowried(instance);
        return instance;
    }

    public object? GetService(Type serviceType)
    {
        var instance = _serviceProvider.GetService(serviceType);
        //Autowried(instance);
        return instance;
    }

    private void Autowried(object? instance)
    {
        if (_serviceProvider == null || instance == null)
            return;

        var flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static;
        var type = instance as Type ?? instance.GetType();
        if (instance is Type)
        {
            instance = null;
            flags |= BindingFlags.Static;
        }
        else
        {
            flags |= BindingFlags.Instance;
        }

        //Feild
        this.ScanAllField(type, instance);

        //Property
        this.ScanAllProperty(type, instance);
    }


    /// <summary>
    /// 扫描信息
    /// </summary>
    /// <param name="type"></param>
    /// <param name="instance"></param>
    /// <returns></returns>
    private void ScanAllField(Type? type, object? instance)
    {
        if (type is null) return;

        var flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static;
        var fields = type.GetFields(flags);

        foreach (var field in fields)
        {
            var autowriedAttr = field.GetCustomAttribute<AutowiredAttribute>();
            if (autowriedAttr == null) continue;

            var dependency = GetService(field.FieldType);
            if (dependency == null) continue;

            field.SetValue(instance, dependency);
        }

        this.ScanAllField(type.BaseType, instance);
    }

    /// <summary>
    /// 获取函数信息
    /// </summary>
    /// <param name="type"></param>
    /// <param name="instance"></param>
    /// <returns></returns>
    private void ScanAllProperty(Type? type, object? instance)
    {
        if (type is null) return;

        var flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static;
        var fields = type.GetProperties(flags);

        foreach (var property in fields)
        {
            var autowriedAttr = property.GetCustomAttribute<AutowiredAttribute>();
            if (autowriedAttr == null) continue;

            var dependency = GetService(property.PropertyType);
            if (dependency == null) continue;

            property.SetValue(instance, dependency);
        }

        this.ScanAllProperty(type.BaseType, instance);
    }


}
